package com.zxr.demo.utils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import javax.crypto.SecretKey;
import java.util.Date;
import java.util.concurrent.TimeUnit;

public class JwtUtil {
    // JWT 密钥，用于签名和验证。在实际应用中，应该保存在配置中，且长度大于 256 位
    private static final String SECRET = "your-very-secret-key-that-is-at-least-256-bits-long";
    private static final SecretKey KEY = Keys.hmacShaKeyFor(SECRET.getBytes());

    // 令牌过期时间，这里设置为 30 分钟
    private static final long EXPIRATION_TIME = TimeUnit.MINUTES.toMillis(30);

    /**
     * 根据用户名生成 JWT 令牌
     *
     * @param username 用户名
     * @return 生成的 JWT 字符串
     */
    public static String generateToken(String username) {
        Date now = new Date();
        Date expiration = new Date(now.getTime() + EXPIRATION_TIME);

        return Jwts.builder()
                .subject(username) // 主题，通常是用户名或用户ID
                .issuedAt(now)     // 签发时间
                .expiration(expiration) // 过期时间
                .signWith(KEY)     // 使用密钥进行签名
                .compact();        // 压缩成 JWT 字符串
    }

    /**
     * 解析并获取 JWT 中的所有 Claims（声明）
     *
     * @param token JWT 字符串
     * @return Claims 对象
     */
    public static Claims parseToken(String token) {
        return Jwts.parser()
                .verifyWith(KEY) // 使用相同的密钥进行验证
                .build()
                .parseSignedClaims(token)
                .getPayload();
    }

    /**
     * 验证 JWT 令牌是否有效
     *
     * @param token JWT 字符串
     * @return 如果令牌有效则返回 true，否则返回 false
     */
    public static boolean validateToken(String token) {
        try {
            Claims claims = parseToken(token);
            // 检查令牌是否过期
            return !claims.getExpiration().before(new Date());
        } catch (Exception e) {
            // 令牌解析失败、过期或签名无效都视为无效
            return false;
        }
    }
    // JwtUtil.java 补充方法
    /**
     * 从令牌中获取用户名
     */
    public static String getUsernameFromToken(String token) {
        Claims claims = Jwts.parser()
                .setSigningKey(KEY)
                .build()
                .parseClaimsJws(token)
                .getBody();
        return claims.getSubject();
    }
}
